Skip to content

Conversation

@stepan-ulyanin
Copy link
Contributor

@stepan-ulyanin stepan-ulyanin commented Dec 30, 2025

Adds a new parameter to the NIOFS FileSystem's copyItem that allows to atomically overwrite regular files and symbolic links.

Note that I opted in to not implement the overwrite for directories in this PR as it seems that there is no atomic way to overwrite directory trees on Posix systems - do we want to do it non-atomically?

Motivation:

Per #3403 it is not uncommon to want to copy an item and not care if the copied item overwrites an existing one.

Modifications:

  1. Adds a new overwriting: Bool parameter to NIOFS FileSystem's copyItem.
  2. Adds new syscall wrappers for TOCTOU-protected atomic operations:
    1. system_renameatx_np / Syscall.rename(from:relativeTo:to:relativeTo:options:) - Darwin directory-relative rename
    2. system_symlinkat / Syscall.symlinkat - create symlink relative to directory FD
    3. system_unlinkat / Syscall.unlinkat - unlink file relative to directory FD
  3. Implements atomic overwrite for both regular files and symbolic links.
    1. For regular files:
      1. On Darwin: a COPYFILE_UNLINK flag is added to copyfile(2)
      2. On Linux: an atomic rename is used - the file is copied to a temporary destination first and then atomically renamed, using renameat2(2) which overwrites the existing file.
    2. For symlinks:
      1. On Darwin: an atomic rename is used - the symlink is copied to a temporary destination first and then atomically renamed, using renameatx_np(2) which overwrites the existing symlink.
      2. On Linux: an atomic rename is used - the symlink is copied to a temporary destination first and then atomically renamed, using renameat2(2) which overwrites the existing symlink.
  4. Adds test cases to the integration test suite.
  5. Updates the _NIOFileSystem FileSystem's copyItem for backward compatibility.

Tests

Syscall tests:

  • test_symlinkat
  • test_unlinkat
  • test_renameatx_np

Integration tests:

  • testCopyFileOverwritingExistingFile
  • testCopyFileOverwritingNonExistingFile
  • testCopyFileOverwritingCleansUpTempFile
  • testCopyFileOverwritingPreservesPermissions
  • testCopySymlinkOverwritingExistingSymlink
  • testCopySymlinkOverwritingNonExistingSymlink
  • testCopySymlinkOverwritingCleansUpTempLink
  • testCopyFileOverwritingExistingSymlink
  • testCopySymlinkOverwritingExistingFile

Result:

Users will be able to copy a regular file or a symbolic link, overwriting an existing regular file or existing symbolic link.

@stepan-ulyanin stepan-ulyanin marked this pull request as ready for review December 30, 2025 06:51
@stepan-ulyanin stepan-ulyanin marked this pull request as draft December 30, 2025 06:59
@stepan-ulyanin stepan-ulyanin marked this pull request as draft January 22, 2026 05:45
@stepan-ulyanin stepan-ulyanin marked this pull request as ready for review January 24, 2026 01:46
@stepan-ulyanin stepan-ulyanin requested a review from Lukasa January 24, 2026 01:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🆕 semver/minor Adds new public API.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants